package com.harth.blemultiplatform.ble

import android.content.Context
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import no.nordicsemi.kotlin.ble.client.android.CentralManager
import no.nordicsemi.kotlin.ble.client.android.native
import no.nordicsemi.kotlin.ble.core.Manager
import kotlin.time.Duration

class NativeCentralManager(private val context: Context): ICentralManager {
    val scope = CoroutineScope(SupervisorJob())

    val centralManager: CentralManager = CentralManager.Factory.native(context, scope)

    override fun getPeripheralsById(ids: List<String>): List<IPeripheral> {
        return centralManager.getPeripheralsById(ids).map { peripheral ->
            NativePeripheral(
                peripheral = peripheral,
                scope = scope
            )
        }
    }

    override fun scan(timeout: Duration): Flow<IScanResult> {
        return centralManager.scan(timeout)
            .map {
                NativeScanResult(it, scope)
            }
    }

    override suspend fun connect(peripheral: IPeripheral) {
        centralManager.getPeripheralById(peripheral.address)?.let {
            centralManager.connect(it)
        }
    }

    override val state: StateFlow<ICentralManager.State>
        get() = centralManager.state.map { state ->
            when (state){
                Manager.State.POWERED_OFF -> ICentralManager.State.POWERED_OFF
                Manager.State.POWERED_ON -> ICentralManager.State.POWERED_ON
                Manager.State.RESETTING -> ICentralManager.State.RESETTING
                Manager.State.UNKNOWN -> ICentralManager.State.UNKNOWN
                Manager.State.UNSUPPORTED -> ICentralManager.State.UNSUPPORTED
            }
        }.stateIn(
            scope = scope,
            started = SharingStarted.Eagerly,
            initialValue = ICentralManager.State.UNKNOWN
        )

    override fun close() {
        centralManager.close()
    }
}